// app/service/smart_learning_service.js
'use strict';

const { Service } = require('egg');

class SmartLearningService extends Service {
  // 学习用户确认模式
  async learnFromUserActions(userId) {
    const { ctx } = this;
    
    try {
      // 获取用户的历史匹配确认记录
      const userMatches = await ctx.model.ReconciliationResultModel.findAll({
        where: {
          confirmedBy: userId,
          matchStatus: 'confirmed'
        },
        include: [
          { model: ctx.model.SalesOrderModel },
          { model: ctx.model.BankTransactionModel }
        ],
        order: [['confirmedAt', 'DESC']],
        limit: 100 // 最近100条记录
      });
      
      if (userMatches.length === 0) {
        return {
          amountTolerance: 0,
          nameSimilarityThreshold: 0.8,
          timeWindow: 30
        };
      }
      
      // 分析金额容差
      const amountDifferences = [];
      const nameSimilarities = [];
      
      for (const match of userMatches) {
        const order = match.salesOrder;
        const transaction = match.bankTransaction;
        
        if (order && transaction) {
          // 计算金额差异
          const diff = Math.abs(order.orderAmount - transaction.amount);
          amountDifferences.push(diff);
          
          // 计算名称相似度
          const similarity = this.calculateNameSimilarity(order.customerName, transaction.payerName);
          nameSimilarities.push(similarity);
        }
      }
      
      // 计算平均容差
      const avgAmountDiff = amountDifferences.reduce((sum, diff) => sum + diff, 0) / amountDifferences.length;
      const avgNameSimilarity = nameSimilarities.reduce((sum, sim) => sum + sim, 0) / nameSimilarities.length;
      
      return {
        amountTolerance: avgAmountDiff,
        nameSimilarityThreshold: avgNameSimilarity / 100,
        timeWindow: 30 // 默认30天时间窗口
      };
    } catch (error) {
      ctx.logger.error('学习用户行为失败:', error);
      // 返回默认值
      return {
        amountTolerance: 0,
        nameSimilarityThreshold: 0.8,
        timeWindow: 30
      };
    }
  }
  
  // 计算名称相似度
  calculateNameSimilarity(name1, name2) {
    // 简化的实现，实际应用中应使用更复杂的算法
    if (name1 === name2) return 100;
    
    // 检查包含关系
    if (name1.includes(name2) || name2.includes(name1)) {
      return 80;
    }
    
    // 计算编辑距离相似度
    const distance = this.editDistance(name1.toLowerCase(), name2.toLowerCase());
    const maxLength = Math.max(name1.length, name2.length);
    
    if (maxLength === 0) return 100;
    
    return Math.round(((maxLength - distance) / maxLength) * 100);
  }
  
  // 计算编辑距离
  editDistance(str1, str2) {
    const matrix = [];
    
    for (let i = 0; i <= str2.length; i++) {
      matrix[i] = [i];
    }
    
    for (let j = 0; j <= str1.length; j++) {
      matrix[0][j] = j;
    }
    
    for (let i = 1; i <= str2.length; i++) {
      for (let j = 1; j <= str1.length; j++) {
        if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
          matrix[i][j] = matrix[i - 1][j - 1];
        } else {
          matrix[i][j] = Math.min(
            matrix[i - 1][j - 1] + 1, // 替换
            matrix[i][j - 1] + 1,     // 插入
            matrix[i - 1][j] + 1      // 删除
          );
        }
      }
    }
    
    return matrix[str2.length][str1.length];
  }
  
  // 自适应阈值调整 - 符合AC-ALGO-002验收标准
  calculateAdaptiveThreshold(dataQuality) {  // 移除了async关键字
    // 根据数据质量调整置信度阈值
    if (dataQuality === 'high') {
      return 85; // 高质量数据使用较高阈值
    } else if (dataQuality === 'medium') {
      return 70; // 中等质量数据使用中等阈值
    } else {
      return 50; // 低质量数据使用较低阈值
    }
  }
  
  // 根据时间范围获取阈值
  getThresholdForDateRange(startDate, endDate) {
    const start = new Date(startDate);
    const end = new Date(endDate);
    const diffTime = Math.abs(end - start);
    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    
    // 近期数据匹配阈值可以适当降低
    if (diffDays <= 30) {
      return 60; // 最近30天
    } else if (diffDays <= 90) {
      return 70; // 最近3个月
    } else {
      return 80; // 更早的数据
    }
  }
}

module.exports = SmartLearningService;